package com.sentinel.demo.pull.file.init;

import com.alibaba.csp.sentinel.datasource.FileRefreshableDataSource;
import com.alibaba.csp.sentinel.datasource.FileWritableDataSource;
import com.alibaba.csp.sentinel.datasource.ReadableDataSource;
import com.alibaba.csp.sentinel.datasource.WritableDataSource;
import com.alibaba.csp.sentinel.init.InitFunc;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.csp.sentinel.transport.util.WritableDataSourceRegistry;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.sentinel.demo.common.FileUtil;
import com.sentinel.demo.common.SpringBeanUtils;
import com.sentinel.demo.pull.file.config.SentinelAspectConfiguration;

import java.util.List;

/**
 * Pull模式 - 持久化到本地文件 ，不需要对 Sentinel 控制台进行改造
 *
 * @author dsy on 2019/12/7
 */
public class FileDataSourceInit implements InitFunc {

    /**
     * sentinel规则（限流）持久化文件路径
     */
    private String persistenceFilePath;

    public FileDataSourceInit() {
        this.persistenceFilePath = SpringBeanUtils.getApplicationContext().getBean(SentinelAspectConfiguration.class).getPersistenceFilePath();
    }

    @Override
    public void init() throws Exception {
        String flowRulePath = FileUtil.getFile(persistenceFilePath).getAbsolutePath();//"E:\\IdeaProjects\\staging-mall\\rule\\FlowRule.json";//URLDecoder.decode(getClass().getClassLoader().getResource("FlowRule.json").getFile(), "UTF-8");;

        ReadableDataSource<String, List<FlowRule>> ds = new FileRefreshableDataSource<>(flowRulePath, source -> JSON.parseObject(source, new TypeReference<List<FlowRule>>() {}));
        // 将可读数据源注册至 FlowRuleManager.
        FlowRuleManager.register2Property(ds.getProperty());

        WritableDataSource<List<FlowRule>> wds = new FileWritableDataSource<>(flowRulePath, this::encodeJson);
        // 将可写数据源注册至 transport 模块的 WritableDataSourceRegistry 中.
        // 这样收到控制台推送的规则时，Sentinel 会先更新到内存，然后将规则写入到文件中.
        WritableDataSourceRegistry.registerFlowDataSource(wds);
    }

    private <T> String encodeJson(T t) {
        return JSON.toJSONString(t);
    }
}
